/**
 * word模块文件替换导出
 */
const fs = require('fs');
const path = require('path');
const PizZip = require('pizzip');
const Docxtemplater = require('docxtemplater');
const ImageModule = require('docxtemplater-image-module-free');
const expressions = require('angular-expressions');

const docx2 = require('docx-templates');
const { URL } = require('url');

/**
 * 根据模板文档生成word文档，用docxtemplater库
 * @param {string} inFile 模板文档名
 * @param {object} data 要替换的数据
 * @param {string} outFile 输出文档名
 */
function generateFile (inFile, data, outFile) {
  let rootFolder = '';// 根据目录
  if (process.env.NODE_ENV === 'development') { // 开发环境
    rootFolder = path.join(path.resolve(), 'uploads');
  } else { // 生产环境
    rootFolder = path.join(path.resolve(), '../uploads');
  }
  if (!fs.existsSync(rootFolder)) {
    fs.mkdirSync(rootFolder)
  }

  const inFolder = path.join(rootFolder, 'template'); // 模板目录
  const outFolder = path.join(rootFolder, 'output'); // 输出目录
  if (!fs.existsSync(outFolder)) {
    fs.mkdirSync(outFolder)
  }

  // 以binary格式读取模板文件
  const content = fs.readFileSync(path.join(inFolder, inFile), 'binary');
  const zip = new PizZip(content);
  const doc = new Docxtemplater();
  const opts = {
    centered: false,
    getImage: function (tagValue, tagName) {
      return fs.readFileSync(path.join(rootFolder, '..' + tagValue));
    },
    getSize: function (img, tagValue, tagName) {
      // return [280, 280];
      const sizeOf = require('image-size');
      const sizeObj = sizeOf(img);

      const fixedSize = 280;
      let width = fixedSize, height = fixedSize;
      if (sizeObj.width > sizeObj.height) {
        height = ~~((width * sizeObj.height) / sizeObj.width);
      } else {
        width = ~~((height * sizeObj.width) / sizeObj.height);
      }
      return [width, height];
    }
  }

  doc.attachModule(new ImageModule(opts))
  doc.loadZip(zip);
  doc.setData(data); // 设置数据

  expressions.filters.lower = function (input) {
    // This condition should be used to make sure that if your input is
    // undefined, your output will be undefined as well and will not
    // throw an error
    if (!input) return input;
    return input.toLowerCase();
  }
  function angularParser (tag) {
    if (tag === '.') {
      return {
        get: function (s) { return s; }
      };
    }
    const expr = expressions.compile(
      tag.replace(/(’|‘)/g, "'").replace(/(“|”)/g, '"')
    );

    return {
      get: function (scope, context) {
        let obj = {};
        const scopeList = context.scopeList;
        const num = context.num;
        for (let i = 0, len = num + 1; i < len; i++) {
          obj = Object.assign(obj, scopeList[i]);
        }
        return expr(scope, obj);
      }
    };
  }
  doc.setOptions({ parser: angularParser });

  try {
    // 数据会自动根据属性把所对应的点位符替换成数据
    doc.render();
  } catch (error) {
    const err = {
      message: error.message,
      name: error.name,
      stack: error.stack,
      properties: error.properties
    }
    console.log(JSON.stringify(err));
    /*
    The error thrown here contains additional information when logged with JSON.stringify (it contains a property object).
    */
    throw error;
  }

  const buf = doc.getZip().generate({ type: 'nodebuffer' });
  /* buf is a nodejs buffer, you can either write it to a file or do anything else with it. */
  fs.writeFileSync(path.join(outFolder, outFile), buf);

  // return '/uploads/output/' + outFile;
  return {
    url: path.join('uploads/output', outFile),
    file: outFile
  };
}

/**
 * 根据模板文档生成word文档，用docx-templates库
 * @param {string} inFile 模板文档名
 * @param {object} data 要替换的数据
 * @param {string} outFile 输出文档名
 * @param {string} domain 主域名，用于替换html中img的src
 */
async function generateFile2 (inFile, data, outFile, domain) {
  let rootFolder = '';// 根据目录
  if (process.env.NODE_ENV === 'development') { // 开发环境
    rootFolder = path.join(path.resolve(), 'uploads');
  } else { // 生产环境
    rootFolder = path.join(path.resolve(), '../uploads');
  }
  if (!fs.existsSync(rootFolder)) {
    fs.mkdirSync(rootFolder)
  }

  const inFolder = path.join(rootFolder, 'template'); // 模板目录
  const outFolder = path.join(rootFolder, 'output'); // 输出目录
  if (!fs.existsSync(outFolder)) {
    fs.mkdirSync(outFolder)
  }

  // 读取模板文件
  const template = fs.readFileSync(path.join(inFolder, inFile));

  // 执行替换
  const buffer = await docx2.createReport({
    template,
    data,
    cmdDelimiter: ['{', '}'],
    additionalJsContext: {
      showLocalImage: (file, size) => {
        const sizeOf = require('image-size');
        const sizeObj = sizeOf(path.join(rootFolder, '..', file));

        const fixedSize = size || 5; // cm
        let width = fixedSize, height = fixedSize;
        if (sizeObj.width > sizeObj.height) {
          height = ~~((width * sizeObj.height) / sizeObj.width);
        } else {
          width = ~~((height * sizeObj.width) / sizeObj.height);
        }
        return {
          width,
          height,
          data: fs.readFileSync(path.join(rootFolder, '..', file)),
          extension: `.${file.split('.').reverse()[0]}`
        }
      },
      handleHtml: code => {
        // 把html里，img的src加上前缀
        function imgSrcReplace (htmlstr, domainURL) {
          // let regex3 = new RegExp(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi);

          const htmlstr1 = htmlstr.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function (match, capture) {
            let newSrc = capture;
            // 无前缀加上
            if (capture.indexOf('http') != 0) {
              newSrc = new URL(capture, global.domainHost).href;
            }
            // console.log('*********', capture, newSrc);
            return '<img src="' + newSrc + '" />';

            /* let newImg = capture; // wps居然不支持base64
            // 转base64
            if (capture.indexOf('http') != 0 && capture.indexOf(';base64,') < 0) { // 本地图片
              if (capture.indexOf('default_img.jpg') >= 0) {
                newImg = new URL(capture, domainURL).href;
              } else {
                newImg = tools.localImgToBase64(capture);
              }
            } *//*  else if (capture.indexOf('http') == 0 && capture.indexOf(';base64,') < 0) { // 网络图片
              newImg = await tools.urlImgToBase64(capture);
            } */
            // return newImg && '<img src="' + newImg + '" style="max-width: 50mm" />';
          });

          // regex3 = null;
          return htmlstr1;
        }
        return `${imgSrcReplace(code, domain)}`;
      }
    }
  });

  // 输出
  fs.writeFileSync(path.join(outFolder, outFile), buffer);

  // return '/uploads/output/' + outFile;
  return {
    url: path.join('uploads/output', outFile),
    file: outFile
  };
}

exports.generateFile = generateFile;
exports.generateFile2 = generateFile2;
